﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using GalaSoft.MvvmLight.Command;
using JustinAngel.Neurons.Framework;
using JustinAngel.UnitedNationsNews.CustomControls;
using JustinAngel.UnitedNationsNews.ItemViewMoels;
using JustinAngel.UnitedNationsNews.Framework.Helpers;
using Ninject;

namespace JustinAngel.UnitedNationsNews.Pages.Article
{
    public class ArticlePageViewModel : VViewModelBase
    {
        public ArticlePageViewModel()
        {
        }
        protected override bool IsAutomaticallyTombstoneAndRestoreViewModel
        {
            get { return true; }
        }

        protected override Type AutomaticallyTombstoneAndRestoreViewModelType
        {
            get
            {
                return typeof(ArticleItemViewModel);
            }
        }

        protected override void OnApplicationDeactivated(Neurons.Framework.Messages.ApplicationDeactivatedMessage obj)
        {
            base.OnApplicationDeactivated(obj);
            WriteStateForProperty("currentParagraph", currentParagraph == 0 ? 0 : currentParagraph - 1); // -1 to compensate for the Speech Algorithm jumping +1 paragraph on tombstoning
        }

        private bool _wasCurrentParagraphSetAfterZombification = false;
        protected override void CheckOnApplicationActivated()
        {
            base.CheckOnApplicationActivated();
            
            if (CanReadStateForProperty("currentParagraph"))
            {
                currentParagraph = ReadStateForProperty<int>("currentParagraph");
                _wasCurrentParagraphSetAfterZombification = true; 
            }
        }

        public override void OnDataSet()
        {
            base.OnDataSet();
        }

        public ArticleItemViewModel RealData
        {
            get { return (ArticleItemViewModel)Data; }
        }
        
        public List<string> Paragraphs
        {
            get
            {
                return RealData.Paragraphs.Select(p => p + Environment.NewLine).ToList();
            }
        }
        
       // hides the image background until databinding occurs
        public Brush ImageBackgroundColour
        {
            get { return new SolidColorBrush(Color.FromArgb(255, 91, 146, 229)); }
        }

        private void InitTextToSpeech()
        {
            if (_speech != null)
                _speech.Dispose();
            _speech = new Speech();
            _speech.ReadyToSpeak += new EventHandler(_speech_ReadyToSpeak);
            _speech.IsSpeakingChanged += new EventHandler<Framework.EventArgs<bool>>(_speech_IsSpeakingChanged);
            _speech.SpeechFailed += new EventHandler(_speech_SpeechFailed);
            IsLoadingNextMP3 = false;

            if (_wasCurrentParagraphSetAfterZombification)
            {
                _wasCurrentParagraphSetAfterZombification = false;
            }
            else
            {
                currentParagraph = 0;
            }
        }

        [Inject]
        public IDialogService DialogService { get; set; }

        void _speech_SpeechFailed(object sender, EventArgs e)
        {
            BeginInvokeOnUIThread(()=>
            {
                IsLoadingNextMP3 = false;
                MessengerInstance.Send(new ArticleTextToSpeechStartedOrPause(false));
                DialogService.ShowMessageBox("We couldn't read text-to-speech on this article. Please try again later.", "We're sorry", MessageBoxButton.OK);
            });
        }

        private Speech _speech = new Speech();

        public ICommand PauseTextToSpeech
        {
            get { return new RelayCommand(OnPauseTextToSpeech); }
        }

        private void OnPauseTextToSpeech()
        {
            _speech.PauseSpeaking();
            MessengerInstance.Send(new ArticleTextToSpeechStartedOrPause(false));
        }

        public ICommand StartTextToSpeech
        {
            get { return new RelayCommand(OnStartTextToSpeech); }
        }

        private const string appId = "6711AE32090B54D69071A6E2C29C9369624FE468";

        private int currentParagraph = 0;

        private void OnStartTextToSpeech()
        {
            if (!_speech.IsSpeaking)
            {
                SetupTextToSpeechForParagraphIndex(currentParagraph);
            }
            else
            {
                _speech.ResumeSpeaking();
            }
            MessengerInstance.Send(new ArticleTextToSpeechStartedOrPause(true));
        }


        private void SetupTextToSpeechForParagraphIndex(int paragraphIndex)
        {
            if (paragraphIndex >= Paragraphs.Count)
            {
                currentParagraph = 0;
                IsLoadingNextMP3 = false;
                MessengerInstance.Send(new ArticleTextToSpeechStartedOrPause(false));
                return; 
            }

            IsLoadingNextMP3 = true;
            var currentText = Paragraphs[paragraphIndex];
            _speech.StartTextToSpeech(currentText);
            MessengerInstance.Send(new ArticleFocusOnParagraphMessage(currentText));
        }

        void _speech_ReadyToSpeak(object sender, EventArgs e)
        {
            if (_speech != null)
            {
                _speech.Speak();
                IsLoadingNextMP3 = false;
            }
        }


        void _speech_IsSpeakingChanged(object sender, Framework.EventArgs<bool> e)
        {
            if (e.Value == false)
            {
                currentParagraph++;
                SetupTextToSpeechForParagraphIndex(currentParagraph);
            }
        }

        private bool _isLoadingNextMp3;
        public bool IsLoadingNextMP3
        {
            get { return _isLoadingNextMp3; }
            set
            {
                _isLoadingNextMp3 = value;
                RaisePropertyChangedAndUpdateVSM(() => IsLoadingNextMP3, value);
            }
        }

        public override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs navigationEventArgs)
        {
            if (_speech != null)
            {
                _speech.Dispose();
                _speech = null;
            }
            
            base.OnNavigatedFrom(navigationEventArgs);
        }

        public override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs navigationEventArgs)
        {
            base.OnNavigatedTo(navigationEventArgs);
            InitTextToSpeech();
        }
    }
}
